home *** CD-ROM | disk | FTP | other *** search
/ X User Tools / X User Tools (O'Reilly and Associates)(1994).ISO / sources / xman / handler.c < prev    next >
C/C++ Source or Header  |  1994-09-27  |  17KB  |  632 lines

  1. /*
  2.  * xman - X window system manual page display program.
  3.  *
  4.  * $XConsortium: handler.c,v 1.20 91/06/05 14:50:29 dave Exp $
  5.  *
  6.  * Copyright 1987, 1988 Massachusetts Institute of Technology
  7.  *
  8.  * Permission to use, copy, modify, and distribute this software and its
  9.  * documentation for any purpose and without fee is hereby granted, provided
  10.  * that the above copyright notice appear in all copies and that both that
  11.  * copyright notice and this permission notice appear in supporting
  12.  * documentation, and that the name of M.I.T. not be used in advertising or
  13.  * publicity pertaining to distribution of the software without specific,
  14.  * written prior permission.  M.I.T. makes no representations about the
  15.  * suitability of this software for any purpose.  It is provided "as is"
  16.  * without express or implied warranty.
  17.  *
  18.  * Author:    Chris D. Peterson, MIT Project Athena
  19.  * Created:   October 29, 1987
  20.  */
  21.  
  22. #include "globals.h"
  23. #include "vendor.h"
  24.  
  25. static void PutUpManpage();
  26. static void ToggleBothShownState();
  27.  
  28. /*    Function Name: OptionCallback
  29.  *    Description: This is the callback function for the callback menu.
  30.  *    Arguments: w - the widget we are calling back from. 
  31.  *                 globals_pointer - a pointer to the psuedo globals structure
  32.  *                                  for this manpage.
  33.  *                 junk - (call data) not used.
  34.  *    Returns: none.
  35.  */
  36.  
  37. /*ARGSUSED*/
  38. void
  39. OptionCallback(w, pointer, junk)
  40. Widget w;
  41. XtPointer pointer;
  42. XtPointer junk;        /* unused */
  43. {
  44.   ManpageGlobals * man_globals = (ManpageGlobals *) pointer;
  45.   String params;
  46.   Cardinal num_params = 1;
  47.  
  48.   if ( w == man_globals->search_entry )
  49.     PopupSearch(XtParent(w), NULL, NULL, NULL);
  50.   else if (w == man_globals->dir_entry) {       /* Put Up Directory */
  51.     params = "Directory";
  52.     GotoPage(XtParent(w), NULL, ¶ms, &num_params);
  53.   }
  54.   else if (w == man_globals->manpage_entry ) {  /* Put Up Man Page */
  55.     params = "ManualPage";
  56.     GotoPage(XtParent(w), NULL, ¶ms, &num_params);
  57.   }
  58.   else if ( w == man_globals->help_entry )      /* Help */
  59.     PopupHelp(XtParent(w), NULL, NULL, NULL);
  60.   else if ( w == man_globals->both_screens_entry ) /*Toggle Both_Shown State.*/
  61.     ToggleBothShownState(man_globals);
  62.   else if ( w == man_globals->remove_entry)     /* Kill the manpage */
  63.     RemoveThisManpage(XtParent(w), NULL, NULL, NULL);
  64.   else if ( w == man_globals->open_entry)       /* Open new manpage */
  65.     CreateNewManpage(XtParent(w), NULL, NULL, NULL);
  66.   else if ( w == man_globals->version_entry)    /* Get version */
  67.     ShowVersion(XtParent(w), NULL, NULL, NULL);
  68.   else if ( w == man_globals->quit_entry)      /* Quit. */
  69.     Quit(XtParent(w), NULL, NULL, NULL);
  70. }
  71.  
  72. /*      Function Name: ToggleBothShownState;
  73.  *      Description: toggles the state of the both shown feature.
  74.  *      Arguments: man_globals - the man globals structure.
  75.  *      Returns: none.
  76.  */
  77.  
  78. /*
  79.  * I did not have a two state widget, which is the way this
  80.  * should really be done.  1/22/88 - CDP.
  81.  */
  82.  
  83. static void
  84. ToggleBothShownState(man_globals)
  85. ManpageGlobals * man_globals; 
  86. {
  87.   char * label_str;
  88.   Arg arglist[1];
  89.  
  90.   if (man_globals->both_shown == TRUE) {
  91.     label_str = SHOW_BOTH;
  92.     if (man_globals->dir_shown)
  93.       XtUnmanageChild(man_globals->manpagewidgets.manpage);
  94.     else
  95.       XtUnmanageChild(man_globals->manpagewidgets.directory);
  96.   }
  97.   else {
  98.     Widget manpage = man_globals->manpagewidgets.manpage;
  99.     Widget dir = man_globals->manpagewidgets.directory;
  100.     
  101.     label_str = SHOW_ONE;
  102.  
  103.     XtSetArg(arglist[0], XtNpreferredPaneSize, resources.directory_height);
  104.     XtSetValues(dir, arglist, (Cardinal) 1);
  105.  
  106.     if (!man_globals->dir_shown) {
  107.       XtUnmanageChild(manpage);
  108.       XtManageChild(dir);
  109.     }
  110.     XtManageChild(manpage);
  111.   }
  112.   man_globals->both_shown = !man_globals->both_shown;
  113.   
  114.   if (man_globals->dir_shown)
  115.     ChangeLabel(man_globals->label,
  116.         man_globals->section_name[man_globals->current_directory]);
  117.   else
  118.     ChangeLabel(man_globals->label, man_globals->manpage_title);
  119.   
  120.   XtSetArg(arglist[0], XtNlabel, label_str);
  121.   XtSetValues(man_globals->both_screens_entry, arglist, ONE);
  122.   
  123.   /* if both are shown there is no need to switch between the two. */
  124.  
  125.   XtSetArg(arglist[0], XtNsensitive, !man_globals->both_shown);
  126.   XtSetValues(man_globals->manpage_entry, arglist, ONE);
  127.   XtSetValues(man_globals->dir_entry, arglist, ONE);
  128. }
  129.  
  130. /*    Function Name: Popup
  131.  *    Description: This function pops up the given widget under the cursor.
  132.  *    Arguments: w - the widget to popup.
  133.  *                 grab_kind - the kind of grab to register.
  134.  *    Returns: none
  135.  */
  136.  
  137. /* How far off the top of the widget to have the initial cursor postion. */
  138.  
  139. #define OFF_OF_TOP 25
  140.  
  141. void
  142. Popup(w, grab_kind)
  143. Widget w;
  144. XtGrabKind grab_kind;
  145. {
  146.   int x_root,y_root,y_pos,garbage;
  147.   unsigned int mask;
  148.   Window junk_window;
  149.  
  150.   XQueryPointer(XtDisplay(w), XtWindow(w), &junk_window, &junk_window,
  151.         &x_root, &y_root, &garbage, &garbage, &mask);
  152.  
  153.   y_pos = OFF_OF_TOP - Height(w)/2 - BorderWidth(w);
  154.   PositionCenter(w, x_root, y_root, y_pos, 0, 2, 2);
  155.   XtPopup(w, grab_kind);
  156. }
  157.  
  158. /*    Function Name: PutUpManpage
  159.  *    Description: Puts the manpage on the display.
  160.  *    Arguments: man_globals - a pointer to the psuedo globals structure
  161.  *                                  for this manpage.
  162.  *                 file - the file to display.
  163.  *    Returns: none.
  164.  */
  165.  
  166. static void
  167. PutUpManpage(man_globals, file)
  168. ManpageGlobals * man_globals;
  169. FILE * file;
  170. {
  171.   String params = "ManualPage";
  172.   Cardinal num_params = 1;
  173.   
  174.   if (file == NULL)
  175.     return;
  176.  
  177.   OpenFile(man_globals, file);
  178.   fclose(file);
  179.  
  180.   if (!man_globals->both_shown) {
  181.     Arg arglist[1];
  182.     XtSetArg(arglist[0], XtNsensitive, TRUE);
  183.     XtSetValues(man_globals->manpage_entry, arglist, ONE);
  184.     XtSetValues(man_globals->both_screens_entry, arglist, ONE);
  185.   }
  186.   GotoPage(man_globals->manpagewidgets.manpage, NULL, ¶ms, &num_params);
  187. }
  188.  
  189. /*    Function Name: DirectoryHandler
  190.  *    Description: This is the callback function for the directory listings.
  191.  *    Arguments: w - the widget we are calling back from. 
  192.  *                 global_pointer - the pointer to the psuedo global structure
  193.  *                                  associated with this manpage.
  194.  *                 ret_val - return value from the list widget.
  195.  *    Returns: none.
  196.  */
  197.  
  198. void
  199. DirectoryHandler(w, global_pointer, ret_val)
  200. Widget w;
  201. XtPointer global_pointer, ret_val;
  202. {
  203.   FILE * file;            /* The manpage file. */
  204.   ManpageGlobals * man_globals = (ManpageGlobals *) global_pointer;
  205.   XawListReturnStruct * ret_struct = (XawListReturnStruct *) ret_val;
  206.  
  207.   file = FindManualFile(man_globals, man_globals->current_directory,
  208.             ret_struct->list_index);
  209.   PutUpManpage(man_globals, file);
  210. }
  211.  
  212. /*    Function Name: DirPopupCallback
  213.  *    Description: This is the callback function for the callback menu.
  214.  *    Arguments: w - the widget we are calling back from. 
  215.  *                 pointer - a pointer to the psuedo globals structure
  216.  *                                  for this manpage.
  217.  *                 junk - (call data) not used.
  218.  *    Returns: none.
  219.  */
  220.  
  221. /*ARGSUSED*/
  222. void
  223. DirPopupCallback(w,pointer,junk)
  224. Widget w;
  225. XtPointer pointer;
  226. XtPointer junk;        /* unused */
  227. {
  228.   ManpageGlobals * man_globals; 
  229.   MenuStruct * menu_struct;
  230.   Widget parent;
  231.   int number;
  232.   int current_box;
  233.  
  234.   menu_struct = (MenuStruct *) pointer;
  235.   man_globals = (ManpageGlobals *) menu_struct->data;
  236.  
  237.   number = menu_struct->number;
  238.   current_box = man_globals->current_directory;
  239.  
  240.   /* We have used this guy, pop down the menu. */
  241.   
  242.   if (number != current_box) {
  243.     /* This is the only one that we know has a parent. */
  244.     parent = XtParent(man_globals->manpagewidgets.box[INITIAL_DIR]);
  245.  
  246.     MakeDirectoryBox(man_globals, parent,
  247.              man_globals->manpagewidgets.box + number, number);
  248.     XtUnmanageChild(man_globals->manpagewidgets.box[current_box]);
  249.     XtManageChild(man_globals->manpagewidgets.box[number]);
  250.  
  251.     XawListUnhighlight(man_globals->manpagewidgets.box[current_box]);
  252.     ChangeLabel(man_globals->label, man_globals->section_name[number]);
  253.     man_globals->current_directory = number;
  254.   }
  255.  
  256.   /* put up directory. */
  257.   if (!man_globals->both_shown) {
  258.     XtUnmanageChild(man_globals->manpagewidgets.manpage);
  259.     XtManageChild(man_globals->manpagewidgets.directory);
  260.   }
  261. }
  262.     
  263. /************************************************************
  264.  *
  265.  * Action Routines.
  266.  *
  267.  ************************************************************/
  268.  
  269. /*    Function Name: SaveFormattedPage
  270.  *    Description: This is the action routine may save the manpage.
  271.  *      Arguments: w - any widget in the widget tree.
  272.  *                 event - NOT USED.
  273.  *                 params, num_params - the parameters paseed to the action
  274.  *                                      routine, can be either Manpage or
  275.  *                                      Directory.
  276.  *      Returns: none.
  277.  */
  278.  
  279. /*ARGSUSED*/
  280. void
  281. SaveFormattedPage(w, event, params, num_params)
  282. Widget w;
  283. XEvent * event;
  284. String * params;
  285. Cardinal * num_params;
  286. {
  287.   ManpageGlobals * man_globals;
  288.   char cmdbuf[BUFSIZ], error_buf[BUFSIZ];
  289.  
  290.   if (*num_params != 1) {
  291.     XtAppWarning(XtWidgetToApplicationContext(w), 
  292.        "Xman - SaveFormattedPage: This action routine requires one argument.");
  293.     return;
  294.   }
  295.  
  296.   man_globals = GetGlobals(w);
  297.  
  298. /*
  299.  * If we are not active then take no action.
  300.  */
  301.  
  302.   if (man_globals->tmpfile == '\0') return;
  303.  
  304.   switch (params[0][0]) {
  305.   case 'S':
  306.   case 's':
  307.  
  308. #ifndef NO_COMPRESS
  309.     if (!man_globals->compress)
  310. #endif
  311.  
  312.       sprintf(cmdbuf, "%s %s %s", COPY, man_globals->tmpfile, 
  313.           man_globals->save_file);
  314.  
  315. #ifndef NO_COMPRESS
  316.     else
  317.       sprintf(cmdbuf, "%s < %s > %s", COMPRESS, man_globals->tmpfile, 
  318.           man_globals->save_file);
  319. #endif
  320.  
  321.     if(! system(cmdbuf)) {
  322.     /* make sure the formatted man page is fully accessible by the world */
  323.     if (chmod(man_globals->save_file, CHMOD_MODE) != 0) {
  324.         sprintf(error_buf,
  325.             "Couldn't set permissions on formatted man page '%s'.\n",
  326.             man_globals->save_file);
  327.         PopupWarning( man_globals, error_buf);
  328.     }
  329.     } else {
  330.     sprintf(error_buf, "Error while executing the command '%s'.\n",
  331.         cmdbuf);
  332.     PopupWarning( man_globals, error_buf);
  333.     }
  334.     break;
  335.   case 'C':
  336.   case 'c':
  337.     break;
  338.   default:
  339.     sprintf(error_buf,"%s %s", "Xman - SaveFormattedPagee:",
  340.         "Unknown argument must be either 'Save' or 'Cancel'.");
  341.     PopupWarning(man_globals, error_buf);
  342.     return;
  343.   }
  344.     
  345. /*
  346.  * We do not need the filename anymore, and have the fd open.
  347.  * We will unlink it.     
  348.  */
  349.  
  350.   unlink(man_globals->tmpfile);
  351.   XtPopdown( XtParent(XtParent(w)) );
  352. }
  353.  
  354. /*      Function Name: GotoPage
  355.  *      Description: The Action routine that switches over to the manpage
  356.  *                   or directory.
  357.  *      Arguments: w - any widget in the widget tree.
  358.  *                 event - NOT USED.
  359.  *                 params, num_params - the parameters paseed to the action
  360.  *                                      routine, can be either Manpage or
  361.  *                                      Directory.
  362.  *      Returns: none.
  363.  */
  364.  
  365. /*ARGSUSED*/
  366. void
  367. GotoPage(w, event, params, num_params)
  368. Widget w;
  369. XEvent * event;
  370. String * params;
  371. Cardinal * num_params;
  372. {
  373.   ManpageGlobals * man_globals;
  374.   char error_buf[BUFSIZ];
  375.   Arg arglist[1];
  376.   Boolean sensitive;
  377.  
  378.   if (*num_params != 1) {
  379.     XtAppWarning(XtWidgetToApplicationContext(w), 
  380.         "Xman - GotoPage: This action routine requires one argument.");
  381.     return;
  382.   }
  383.  
  384.   man_globals = GetGlobals(w);
  385.  
  386.   if (man_globals->both_shown) {
  387.     ChangeLabel(man_globals->label, 
  388.         man_globals->section_name[man_globals->current_directory]);
  389.     return;
  390.   }
  391.  
  392.   switch (params[0][0]) {
  393.   case 'M':
  394.   case 'm':
  395.     XtSetArg(arglist[0], XtNsensitive, &sensitive);
  396.     XtGetValues(man_globals->manpage_entry, arglist, ONE);
  397.     if (sensitive) {
  398.       ChangeLabel(man_globals->label,man_globals->manpage_title);
  399.       XtUnmanageChild(man_globals->manpagewidgets.directory);
  400.       XtManageChild(man_globals->manpagewidgets.manpage);
  401.       man_globals->dir_shown = FALSE;
  402.     }
  403.     break;
  404.   case 'D':
  405.   case 'd':
  406.     ChangeLabel(man_globals->label,
  407.         man_globals->section_name[man_globals->current_directory]);
  408.     XtUnmanageChild(man_globals->manpagewidgets.manpage);
  409.     XtManageChild(man_globals->manpagewidgets.directory);  
  410.     man_globals->dir_shown = TRUE;
  411.     break;
  412.   default:
  413.     sprintf(error_buf,"%s %s", "Xman - GotoPage: Unknown argument must be",
  414.         "either Manpage or Directory.");
  415.     XtAppWarning(XtWidgetToApplicationContext(w), error_buf);
  416.     return;
  417.   }
  418. }
  419.  
  420. /*      Function Name: Quit.
  421.  *      Description: Quits Xman.
  422.  *      Arguments: w - any widget.
  423.  *                 event - NOT USED.
  424.  *                 params, num_params - NOT USED.
  425.  *      Returns: none.
  426.  */
  427.  
  428. /*ARGSUSED*/
  429. void 
  430. Quit(w, event, params, num_params)
  431. Widget w;
  432. XEvent * event;
  433. String * params;
  434. Cardinal * num_params;
  435. {
  436.   XCloseDisplay(XtDisplay(w));
  437.   exit(0);
  438. }
  439.  
  440. /*      Function Name: PopupHelp
  441.  *      Description: Pops up xman's help.
  442.  *      Arguments: w - NOT USED.
  443.  *                 event - NOT USED.
  444.  *                 params, num_params - NOT USED.
  445.  *      Returns: none.
  446.  */
  447.  
  448. /*ARGSUSED*/
  449. void 
  450. PopupHelp(w, event, params, num_params)
  451. Widget w;
  452. XEvent * event;
  453. String * params;
  454. Cardinal * num_params;
  455. {
  456.   if (MakeHelpWidget())
  457.     XtPopup(help_widget,XtGrabNone);
  458. }
  459.  
  460. /*      Function Name: PopupSearch
  461.  *      Description: Pops up this manual pages search widget.
  462.  *      Arguments: w - any widget in this manpage.
  463.  *                 event - NOT USED.
  464.  *                 params, num_params - NOT USED.
  465.  *      Returns: none.
  466.  */
  467.  
  468. /*ARGSUSED*/
  469. void 
  470. PopupSearch(w, event, params, num_params)
  471. Widget w;
  472. XEvent * event;
  473. String * params;
  474. Cardinal * num_params;
  475. {
  476.   ManpageGlobals * man_globals = GetGlobals(w);
  477.   if (!XtIsRealized(man_globals->search_widget)) {
  478.     XtRealizeWidget(man_globals->search_widget);
  479.     AddCursor(man_globals->search_widget, resources.cursors.search_entry);
  480.   }
  481.   Popup(man_globals->search_widget, XtGrabNone);
  482. }
  483.  
  484. /*      Function Name: CreateNewManpage
  485.  *      Description: Creates A New Manual Page.
  486.  *      Arguments: w - NOT USED.
  487.  *                 event - NOT USED.
  488.  *                 params, num_params - NOT USED.
  489.  *      Returns: none.
  490.  */
  491.  
  492. /*ARGSUSED*/
  493. void 
  494. CreateNewManpage(w, event, params, num_params)
  495. Widget w;
  496. XEvent * event;
  497. String * params;
  498. Cardinal * num_params;
  499. {
  500.   (void) CreateManpage(NULL);
  501.   man_pages_shown++;
  502. }
  503.  
  504. /*      Function Name: RemoveThisManpage
  505.  *      Description: Removes a manual page.
  506.  *      Arguments: w - any widget in the manpage.
  507.  *                 event - NOT USED.
  508.  *                 params, num_params - NOT USED.
  509.  *      Returns: none.
  510.  */
  511.  
  512. /*ARGSUSED*/
  513. void 
  514. RemoveThisManpage(w, event, params, num_params)
  515. Widget w;
  516. XEvent * event;
  517. String * params;
  518. Cardinal * num_params;
  519. {
  520.   ManpageGlobals * man_globals = GetGlobals(w);
  521.   
  522.   if (man_globals->This_Manpage != help_widget) {
  523.     RemoveGlobals(man_globals->This_Manpage);
  524.     XtDestroyWidget(man_globals->This_Manpage);
  525.  
  526.     XtFree( (char *) man_globals->section_name);
  527.     XtFree( (char *) man_globals->manpagewidgets.box);
  528.     XtFree( (char *) man_globals);
  529.  
  530.     if ( (--man_pages_shown) == 0)
  531.       Quit(w, NULL, NULL, NULL);  
  532.   }
  533.   else
  534.     XtPopdown(help_widget);
  535. }
  536.  
  537. /*      Function Name: Search
  538.  *      Description: Actually performs a search.
  539.  *      Arguments: w - any widget in the manpage.
  540.  *                 event - NOT USED.
  541.  *                 params, num_params - NOT USED.
  542.  *      Returns: none.
  543.  */
  544.  
  545. /*ARGSUSED*/
  546. void 
  547. Search(w, event, params, num_params)
  548. Widget w;
  549. XEvent * event;
  550. String * params;
  551. Cardinal * num_params;
  552. {
  553.   ManpageGlobals * man_globals = GetGlobals(w);
  554.   FILE * file;
  555.  
  556.   XtPopdown(  XtParent(XtParent(w)) );       /* popdown the search widget */
  557.  
  558.   if ( (*num_params < 1) || (*num_params > 2) ) {
  559.     XtAppWarning(XtWidgetToApplicationContext(w), 
  560.       "Xman - Search: This action routine requires one or two arguments.");
  561.     return;
  562.   }
  563.  
  564.   switch(params[0][0]) {
  565.   case 'a':
  566.   case 'A':
  567.     file = DoSearch(man_globals,APROPOS);
  568.     break;
  569.   case 'm':
  570.   case 'M':
  571.     file = DoSearch(man_globals,MANUAL);
  572.     break;
  573.   case 'c':
  574.   case 'C':
  575.     file = NULL;
  576.     break;
  577.   default:
  578.     XtAppWarning(XtWidgetToApplicationContext(w), 
  579.          "Xman - Search: First parameter unknown.");
  580.     file = NULL;
  581.     break;
  582.   }
  583.  
  584.   if ( *num_params == 2 ) 
  585.     switch (params[1][0]) {
  586.     case 'O':
  587.     case 'o':
  588.       if (file != NULL) {
  589.     Widget w;
  590.     char * label;
  591.  
  592.     w = CreateManpage(file);
  593.     man_pages_shown++;
  594.  
  595.     /* Put title into new manual page. */
  596.  
  597.     label = man_globals->manpage_title;
  598.     man_globals = GetGlobals(w);
  599.     strcpy(man_globals->manpage_title, label);
  600.     ChangeLabel(man_globals->label, label);
  601.       }
  602.       break;
  603.     default:
  604.       XtAppWarning(XtWidgetToApplicationContext(w), 
  605.            "Xman - Search: Second parameter unknown.");
  606.       break;
  607.     }
  608.   else {
  609.     PutUpManpage(man_globals, file);
  610.   }
  611. }
  612.  
  613. /*      Function Name: ShowVersion
  614.  *      Description: Show current version.
  615.  *      Arguments: w - any widget in the manpage.
  616.  *                 event - NOT USED.
  617.  *                 params, num_params - NOT USED.
  618.  *      Returns: none.
  619.  */
  620.  
  621. /*ARGSUSED*/
  622. void 
  623. ShowVersion(w, event, params, num_params)
  624. Widget w;
  625. XEvent * event;
  626. String * params;
  627. Cardinal * num_params;
  628. {
  629.   ManpageGlobals * man_globals = GetGlobals(w);
  630.   ChangeLabel(man_globals->label, XMAN_VERSION);
  631. }
  632.